﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Drive.LiveExcelHost.Services
{
    /// <summary>
    /// 群组聊天
    /// </summary>
    class GroupChatService : SocketIOService
    {
        public static List<string> chat_history = new List<string>();
        public long numberOfUsers
        {
            get
            {
                return RedisWebSocketSession.GetUserCount();
            }
        }
        public GroupChatService(Request request, WebSocketSession session) : base(request, session)
        {
        }
        internal override async Task OnSocketIoSessionCreate()
        {
            if (!session.IsSendWelcome)
            {
                session.IsSendWelcome = true;

                //var nickName = RedisUserStore.GetNickName(session.VisitorId);
                //if (nickName == null)
                //{
                //    RedisUserStore.SetNickName(session.VisitorId, $"用户{session.VisitorId}");
                //}
                await RedisPubSub.Subscribe("None", this.session.PushToClient); //大厅消息
                await RedisPubSub.Subscribe(this.session.SessionId, this.session.PushToClient); //私信

                await SessionEnter(session, session.cancellationToken);
            }
        }

        private async Task SessionEnter(WebSocketSession session, CancellationToken token)
        {
            try
            {
                var onlinesUsers = RedisVisitorStatus.GetNumberOfStatusOnline();
                var sessionCount = RedisWebSocketSession.Increase("visitor_" + this.session.VisitorId);

                RedisVisitorStatus.SetStatusOnline(this.session.VisitorId, true);

                var sessionReady =TypedMessage.CreateSessionReady(session.GetBuddy(), new
                {
                    numberOfUsers = numberOfUsers,
                    numberOfOnlineUsers = onlinesUsers,
                    sessionCount = sessionCount
                });
                this.session.PushToClient(this.session.SessionId, sessionReady);
                SendChatHistory();
                if (sessionCount == 1)
                {
                    await SendWelcome(session, true, CancellationToken.None);
                    await RedisPubSub.Publish("None",TypedMessage.CreateBuddyEnter(session.GetBuddy(), new { numberOfUsers = numberOfUsers, numberOfOnlineUsers = onlinesUsers }));
                    //await SendSystem($"\"{session.UserName}\"进入。当前在线人数{n}", token);
                }
                else
                {
                    await SendWelcome(session, false, CancellationToken.None);
                }
            }
            catch (Exception ex)
            {

            }
        }

        private async Task SendWelcome(WebSocketSession session, bool firstSession, CancellationToken token)
        {
            if (firstSession)
            {
                if (session.UserName == "用户" + session.VisitorId)
                {
                    await SendSystem($"使用[我是]命令修改昵称，比如我是张三", token, session);
                }
            }
            else
            {
                await SendSystem("欢迎回来！", token, session);
            }
            await SendSystem("聊天时请友善回复，文明发言，祝你聊的愉快！", token, session);
        }

        private void SendChatHistory()
        {
            List<string> messages = new List<string>();
            lock (chat_history)
            {
                messages = chat_history.ToList();
            }
            foreach (var item in messages)
            {
                session.PushToClient(this.session.SessionId, item);
            }
        }

        private async Task SendSystem(string msg, CancellationToken token, WebSocketSession session = null)
        {
            var message =TypedMessage.CreateSystem(msg);
            if (session != null)
            {
                session.PushToClient(session.SessionId, message);
            }
            else
            {
                AddToHistory(message);
                await RedisPubSub.Publish("None", message);
            }
        }

        public override async Task OnMessageReceived(string type, string content)
        {
            
            if (session.IsSendTooFrenquncy())
            {
                this.session.PushToClient(session.SessionId,TypedMessage.CreateThrottle("[手速太快已屏蔽]"));
            }
            else
            {
                if (content.StartsWith("我是") && content.Length > 2)
                {
                    var uname = content.Substring(2);
                    if (uname.Length > 10)
                    {
                        uname = uname.Substring(0, 10);
                    }

                    var uid = RedisUserStore.GetUserIdByNickName(uname);
                    if (uid != null && long.Parse(uid) != session.VisitorId)
                    {
                        content = $"昵称\"{uname}\"已被占用。";
                        await SendSystem(content, session.cancellationToken, session);
                    }
                    else
                    {
                        content = $"用户{session.VisitorId}设置昵称为\"{uname}\"。";
                        RedisUserStore.SetNickName(session.VisitorId, uname);
                        await SendSystem(content, session.cancellationToken);
                    }
                }
                else
                {
                    await SendBoardcast(session, content, session.cancellationToken);
                }
            }
        }

        private void AddToHistory(string msg)
        {
            lock (chat_history)
            {
                chat_history.Add(msg);
                if (chat_history.Count > 500)
                {
                    chat_history.RemoveAt(0);
                }
            }
        }

        private async Task SendBoardcast(WebSocketSession senderSession, string msg, CancellationToken token)
        {
            var message =TypedMessage.CreateGroupChat(senderSession.GetBuddy(), msg);
            AddToHistory(message);
            await RedisPubSub.Publish("None", message);
        }

        internal override async Task OnSocketIoSessionDestory()
        {
            await RedisPubSub.Unsubscribe("None", this.session.PushToClient); //大厅消息
            await RedisPubSub.Unsubscribe(this.session.SessionId, this.session.PushToClient); //私信

            var sessionCount = RedisWebSocketSession.Decrease("visitor_" + this.session.VisitorId);
            RedisVisitorStatus.SetStatusOnline(this.session.VisitorId, sessionCount > 0);
            if (sessionCount == 0)
            {
                await RedisPubSub.Publish("None",TypedMessage.CreateBuddyLeave(session.GetBuddy(), new
                {
                    numberOfUsers = numberOfUsers,
                    numberOfOnlineUsers = RedisVisitorStatus.GetNumberOfStatusOnline()
                }));
            }
        }
    }
}
